package ias.deepsearch.com.helper.service;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.Log;


import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.http.server.AsyncHttpServer;
import com.koushikdutta.async.http.server.AsyncHttpServerRequest;
import com.koushikdutta.async.http.server.AsyncHttpServerResponse;
import com.koushikdutta.async.http.server.HttpServerRequestCallback;
import com.socks.library.KLog;
import com.yancloud.android.contractclient.CMClientHandler;
import com.yancloud.android.contractclient.databaseHelper.DatabaseDao;
import com.yancloud.android.contractclient.doip.RepoServer;
import com.yancloud.android.contractclient.nativesclient.BaseClient;
import com.yancloud.android.contractclient.nativesclient.DelimiterCodec;
import com.yancloud.android.contractclient.nativesclient.WSHandler;
import com.yancloud.android.manager.IASHandler;
import com.yancloud.android.manager.URICallback;
import com.yancloud.android.manager.URLRegx;
import com.yancloud.android.reflection.get.ServiceFactory;
import com.yancloud.android.reflection.get.CMDManager;
import com.yancloud.android.reflection.get.FileHelper;
import com.yancloud.android.reflection.get.MainServer;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Scanner;

import javax.websocket.ClientEndpointConfig;
import javax.websocket.ContainerProvider;

import ias.deepsearch.com.helper.R;
import ias.deepsearch.com.helper.model.dp.AppInfo;
import ias.deepsearch.com.helper.ui.activity.HomeActivity;
import ias.deepsearch.com.helper.util.ACache;
import ias.deepsearch.com.helper.util.normal.FileUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.internal.logging.InternalLoggerFactory;
import io.netty.util.internal.logging.JdkLoggerFactory;
import retrofit.http.POST;
import rx.Observable;
import rx.Subscriber;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * Created by vector on 17/2/22.
 */

public class DaemonService extends Service {

    AsyncHttpServer server;

    String ip = "127.0.0.1";
    ACache aCache;
    public static final String PACKAGE_NAME = "ias.deepsearch.com.ias";
    private static final String TAG = "DaemonService";

    List<AppInfo> appInfos;

    NotificationCompat.Builder builder;

    Notification notification;

    NotificationManager nm;

    public Service service;
    public static Handler handler;
    public static DaemonService instance;
    private static CMClientHandler client;
    private BaseClient bc;

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        android.support.multidex.MultiDex.install(this);

    }

    @Override
    public void onCreate() {
        DatabaseDao.getInstance(DaemonService.this);
        super.onCreate();
        handler = new Handler();
        //TODO some initial operations
        builder = new NotificationCompat.Builder(this)
                .setContentTitle("移动端DORepository")
                .setSmallIcon(R.drawable.smile);

        notification = builder.build();
        notification.flags = Notification.FLAG_ONGOING_EVENT;
        notification.flags |= Notification.FLAG_NO_CLEAR;
        notification.flags |= Notification.FLAG_FOREGROUND_SERVICE;

        nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        Log.d(TAG, "onCreate is called");
        instance = this;
        try {
            startForeground(1120, notification);

            //  nm.notify(120, notification);
            service = ServiceFactory.getService(this);
            MainServer.main(this);
            RepoServer.startServer();
        } catch (Throwable t) {
            t.printStackTrace();
        }
    }


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return service.onBind(intent);
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int id) {
        String showMessage = intent.getStringExtra("message");
        aCache = FileUtil.getACache();
        getAppsInstalled();
        initServer();
        return START_STICKY;
    }

    //获取本地安装的apk列表
    void getAppsInstalled() {

        Observable.create(new Observable.OnSubscribe<List<AppInfo>>() {
            @Override
            public void call(Subscriber<? super List<AppInfo>> sub) {
                sub.onNext(ias.deepsearch.com.helper.util.normal.Utils.getAppListInfo(DaemonService.this));
            }
        }).subscribeOn(Schedulers.io())
                .subscribe(new Action1<List<AppInfo>>() {
                    @Override
                    public void call(List s) {
                        appInfos = s;
                    }
                });

    }

    public static void register(Class clz, AsyncHttpServer server) {
        try {
            //Force initialized!
            Constructor cons = clz.getConstructor();
            cons.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Method[] methods = clz.getDeclaredMethods();
        for (Method m : methods) {
            URLRegx regx = (m.getAnnotation(URLRegx.class));
            if (regx != null) {
                POST post = m.getAnnotation(POST.class);
                if (post == null)
                    server.get(regx.value(), new URICallback(regx.value(), m));
                else
                    server.post(regx.value(), new URICallback(regx.value(), m));
                KLog.v(TAG, "register: " + regx.value());
            }
        }
    }

    void initServer() {
        KLog.v(TAG, "initServer");
        server = new AsyncHttpServer();
        //重启测试工程
        server.get("/", new HttpServerRequestCallback() {
            @Override
            public void onRequest(AsyncHttpServerRequest request, AsyncHttpServerResponse response) {
                response.send(
                        ias.deepsearch.com.helper.util.normal.Utils.buddha);

            }
        });
        register(IASHandler.class, server);
        register(FileHelper.class, server);
        register(CMDManager.class, server);
        server.setErrorCallback(new CompletedCallback() {
            @Override
            public void onCompleted(Exception ex) {
                ex.printStackTrace();
            }
        });
        // listen on port 6161
        server.listen(6161);

        //
        //  initWebsocket();

        initSocket();


    }

    private void initWebsocket() {
        bc = new BaseClient();


//						System.out.println("GlobalConf.getNodeCenterUrl() URL"+ URL);

        new Thread(new Runnable() {
            @Override
            public void run() {
                for (; ; ) {
                    try {
                        if (!bc.connected()) {
                            String URL = getContent("/sdcard/apiminier/nodecenter.txt");
                            if (URL == null || !URL.startsWith("ws"))
                                URL = "ws://39.106.6.6:1718/SCIDE/NodeCenter";
                            System.out.println("[CMActions] connect to node center:" + URL);
                            ContainerProvider.getWebSocketContainer().connectToServer(bc, ClientEndpointConfig.Builder.create().build(),
                                    URI.create(URL));
                        } else CMDManager.updateAppContract(null);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    private void initSocket() {
        InternalLoggerFactory.setDefaultFactory(JdkLoggerFactory.INSTANCE);

        final Bootstrap b = new Bootstrap();
        b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);
        EventLoopGroup group = new NioEventLoopGroup();
        b.group(group);
        b.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ChannelPipeline p = ch.pipeline();
                        p.addLast(new DelimiterCodec()).addLast(client);
                    }
                });


        new Thread((new Runnable() {
            @Override
            public void run() {
                for (; ; ) {
                    try {
                        String URL = getContent("/sdcard/apiminier/nodecenter.txt");
                        if (URL == null || !URL.startsWith("ws"))
                            URL = "ws://39.106.6.6:1718/SCIDE/NodeCenter";
//						System.out.println("GlobalConf.getNodeCenterUrl() URL"+ URL);
                        URI uri = null;
                        try {
                            uri = new URI(URL);
                        } catch (URISyntaxException e1) {
                            e1.printStackTrace();
                        }
                        if (client == null) {
                            client = new CMClientHandler();


                        }
                        if (!client.controller.syncPing()) {
                            System.out.println(
                                    "[CMActions] connect to node center:" + uri.getHost() + " : " + uri.getPort());
                            b.connect(uri.getHost(), uri.getPort()).sync().channel();
                        }


                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        })).start();
    }

    public static void notifyFloatWindow(String content) {
        Uri notifyFloatUri = Uri.parse("content://ias.deepsearch.com.ias.provider.DatasProvider/notify_float");
        instance.getContentResolver().query(notifyFloatUri, null, null, null, content);
    }

    public static void post(Runnable r) {
        handler.post(r);
    }

    public static final String getContent(String path) {
        try {
            Scanner sc = new Scanner(new FileInputStream(path));
            return sc.nextLine();
        } catch (Exception e) {
            System.err.println("[FileUtil] getContent Meets Exception:"
                    + e.getMessage());
            // e.printStackTrace();
            return null;
        }
    }
}
